package msu.ml.util;

public class Location
{
   private double lat;
   private double lon;
   private double geoidHeight;
   private double orthoHeight;

   public enum ArcType
   {
      ALL,
      DEGREES,
      MINUTES,
      SECONDS
   }

   public Location(int latDegree, int latMinute, int latSecond,
         int lonDegree, int lonMinute, int lonSecond)
   { 
      this(toDecimal(latDegree, latMinute, latSecond), 
         toDecimal(lonDegree, lonMinute, lonSecond));
   }

   public Location(double latitude, double longitude)
   {
      this(latitude, longitude, 0.0, 0.0);
   }

   public Location(double latitude, double longitude, double gHeight,
         double oHeight)
   {
      this.lat = latitude;
      this.lon = longitude;
      this.geoidHeight = gHeight;
      this.orthoHeight = oHeight;
   }

   public double getLatitude()
   {
      return this.lat;
   }

   public double getLatitude(ArcType type)
   {
      return parseType(this.lat, type);  
   }

   public double getLongitude()
   {
      return this.lon;
   }

   public double getLongitude(ArcType type)
   {
      return parseType(this.lon, type);  
   }

   private static double toDecimal(double deg, double min, double sec)
   {
      if(deg < 0)
         return deg - (min / 60.0) - (sec / 3600.0);
      else
         return deg + (min / 60.0) + (sec / 3600.0);
   }

   private double parseType(double value, ArcType type)
   {
      int deg;
      int min;
      int sec;

      deg = (int)value;
      value = (value - deg) * 60;
      min = (int)value;
      value = (value - min) * 60;
      sec = (int)value;

      switch(type)
      {
         case DEGREES:
            return deg;
         case MINUTES:
            return min;  
         case SECONDS:
            return sec;
         default:
            return value;
      }
   }

   public double getGeoidHeight()
   {
      return this.geoidHeight;
   }

   public double getOrthoHeight()
   {
      return this.orthoHeight;
   }

   public double getTheta()
   {
      return Math.atan((GeoLocationUtility.B / GeoLocationUtility.A) * Math.tan(Math.toRadians(this.lat)));
   }

   public double getOD()
   {
      return GeoLocationUtility.A * Math.cos(getTheta());
   }

   public double getDP()
   {
      return GeoLocationUtility.B * Math.sin(getTheta());
   }

   public double getOP()
   {
      double od = getOD();
      double dp = getDP();
      return Math.sqrt(od*od + dp*dp);
   }
}


